<?
/**
 * This file is part of XNAT light.
 *
 * XNAT light is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * XNAT light is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with XNAT light.  If not, see <http://www.gnu.org/licenses/>.
 */
namespace NRG\Common;

use NRG\Framework\Exceptions\IllegalArgumentException as IllegalArgumentException;

/**
 * Session model
 *
 * @package NRG\Common
 */
class Session implements \ArrayAccess,\IteratorAggregate
{
    /**
     * Singleton instance
     *
     * @var Session
     */
    protected static $_instance;

    /**
     * Quercus Session object
     *
     * @var Session.java
     */
    protected $_session;

    /**
     * Session properties
     */
    private $_values=Array();

    /**
     * Constructor
     */
    protected function __construct()
    {
        $this->_session = quercus_servlet_request()->getSession();

        // Fetch all attribute names
        $elements=$this->_session->getAttributeNames();

        // Loop through all the names and populate this object's
        // $_values array
        while($elements->hasMoreElements())
        {
            $elem=(string)$elements->nextElement();
            $val=$this->_session->getAttribute($elem);

            // The "user" property is an XFTItem and __processXDATUser
            // will take care of it
            if ($elem == "user")
                $this->_processXDATUser($val);
            else
                //Otherwise, simply storethe key and value
                $this->_values[$elem] = $val;
        }
    }

    /**
     * Singleton getter
     *
     * @return Session
     */
    public static function getInstance()
    {
        if(Session::$_instance === null)
            Session::$_instance = new Session();

        return Session::$_instance;
    }

    /**
     * Get query parameter
     *
     * @param string $token
     * @return mixed
     */
    public function getQueryParam($token)
    {
        if($token == null)
            throw new IllegalArgumentException("Token cannot be null");

        if(isset($_GET[$token]))
            return $_GET[$token];
        else
            return null;
    }

    /**
     * Get POST parameter
     *
     * @param string $token
     * @return mixed
     */
    public function getPostParam($token)
    {
        if($token == null)
            throw new IllegalArgumentException("Token cannot be null");

        if(isset($_POST[$token]))
            return $_POST[$token];
        else
            return null;
    }

    /**
     * Get SESSION parameter
     *
     * @param string $token
     * @return mixed
     */
    public function getSessionParam($token)
    {
        if($token == null)
            throw new IllegalArgumentException("Token cannot be null");

        if(isset($this->_session->getAttribute($token)))
            return $this->_session->getAttribute($token);
        else
            return null;
    }

    /** PHP Magic method to return a session property
     * @return Session property or null
     */
    public function __get($token)
    {
        if (!isset($this->_values["$token"]))
            return null;

        return $this->_values["$token"];
    }

    /** Stores an item in the session
     * @return void
     */
    public function __set($token,$value)
    {
        if ($token==null)
            throw new IllegalArgumentException("Token cannot be null");

        $this->_values["$token"]=$value;
    }

    /** Implements ArrayAccess::offsetSet().
     * allows the user to set values as such:  $session['key']="value"
     * @return void
     */
    public function offsetSet($offset,$value)
    {
        if (is_null($offset))
            $this->_values[]=$value;
        else
            $this->_values[$offset]=$value;
    }

    /** Implements ArrayAccess::offsetExists().
     * @return bool
     */
    public function offsetExists($offset)
    {
        return isset($this->_values[$offset]);
    }

    /** Implements ArrayAccess::offsetUnset().
     * @return void
     */
    public function offsetUnset($offset)
    {
        unset($this->_values[$offset]);
    }

    /** Implements ArrayAccess::offsetGet().
     * Allows the user to request session properties as such: $session['item']
     * @return mixed
     */
    public function offsetGet($offset)
    {
        return isset($this->_values[$offset])?$this->_values[$offset]:null;
    }

    /** Extracts the top level properties from an XDATUser object and stores
     * them as the "user" property of the session
     * @return void
     */
    private function _processXDATUser($item)
    {
        //Return if there is nothing to work with
        if (empty($item))
            return;

        //Use SimpleXML to read the XML value
        $xml=new \SimpleXMLElement($item);

        //Loop over all top level properties and store them in
        //a Session['user'] array
        foreach ($xml as $prop => $val)
            $this->_values["user"][$prop] = (string)$val;
    }


    /** Implements IteratorAggregate::getIterator()
     * @return ArrayIterator
     */
    public function getIterator()
    {
        return new \ArrayIterator($this->_values);
    }
}
